
package com.logic.landseaserver.service.impl;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.JsonMapper;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.LandeaConstants.QueryUesdCodeType;
import com.logic.landseaserver.common.config.FileConfiguration;
import com.logic.landseaserver.common.enums.SystemCodeEnum;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.token.impl.WebBankAccessTokenSerivce;
import com.logic.landseaserver.common.token.impl.WebBankQRTicketSerivce;
import com.logic.landseaserver.common.token.impl.WebBankTicketSerivce;
import com.logic.landseaserver.common.util.DateUtil;
import com.logic.landseaserver.common.util.FileTool;
import com.logic.landseaserver.common.util.StringTools;
import com.logic.landseaserver.common.util.WeBankQRUtil;
import com.logic.landseaserver.common.util.WeBankServiceUtil;
import com.logic.landseaserver.common.util.WeBankUtil;
import com.logic.landseaserver.domain.BillPayment;
import com.logic.landseaserver.domain.Contract;
import com.logic.landseaserver.domain.Customer;
import com.logic.landseaserver.domain.Deposit;
import com.logic.landseaserver.domain.WebankParam;
import com.logic.landseaserver.domain.WebankReconciliation;
import com.logic.landseaserver.models.authcode.service.AuthCodeService;
import com.logic.landseaserver.models.independent.service.BillIndependentService;
import com.logic.landseaserver.models.payment.PaymentConstant.PayType;
import com.logic.landseaserver.persistence.read.BillPaymentReadMapper;
import com.logic.landseaserver.persistence.read.BillReadMapper;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.CustomerReadMapper;
import com.logic.landseaserver.persistence.read.DepositReadMapper;
import com.logic.landseaserver.persistence.read.WebankParamReadMapper;
import com.logic.landseaserver.persistence.read.WebankReconciliationReadMapper;
import com.logic.landseaserver.persistence.write.DepositWriteMapper;
import com.logic.landseaserver.service.IBillPaymentService;
import com.logic.landseaserver.service.IDepositService;
import com.logic.landseaserver.service.IProjectService;
import com.logic.landseaserver.service.IWeBankService;
import com.logic.landseaserver.service.callback.IWebankCallbackHandler;
import com.logic.landseaserver.ws.dto.BillDTO;
import com.logic.landseaserver.ws.dto.CheckPayDTO;
import com.logic.landseaserver.ws.dto.DepositDTO;
import com.logic.landseaserver.ws.dto.ProjectDetailDTO;
import com.logic.landseaserver.ws.dto.WeBankPayCheckDTO;
import com.logic.landseaserver.ws.dto.WeBankPayCheckReqDTO;
import com.logic.landseaserver.ws.dto.WeBankPayDTO;
import com.logic.landseaserver.ws.dto.WeBankPayRespDTO;
import com.logic.landseaserver.ws.dto.WebankPayCallBackRequest;
import com.logic.landseaserver.ws.dto.WebankQRPayCallBackRequest;
import com.logic.landseaserver.ws.dto.WebankQRPayCallBackRequestWapper;
import com.logic.landseaserver.ws.dto.WebankQRPaymentNotify;
import com.logic.landseaserver.ws.dto.WebankQRPaymentNotifyRequest;
import com.logic.system.AppContext;

import net.sf.json.JSONObject;

@Service
public class WeBankServiceImpl implements IWeBankService
{
    
    private static final Logger LOG = LoggerFactory.getLogger(WeBankServiceImpl.class);
    
    private WeBankUtil instance = WeBankUtil.getInstance();
    
    private WeBankQRUtil QRinstance = WeBankQRUtil.getInstance();
    
    @Autowired
    private AppContext appContext;
    
    @Autowired
    private IBillPaymentService iBillPaymentService;
    
    @Autowired
    private IDepositService iDepositServiceImpl;
    
    @Autowired
    private ContractReadMapper contractReadMapper;
    
    @Autowired
    private IProjectService projectService;
    
    @Autowired
    private DepositReadMapper depositReadMapper;
    
    @Autowired
    private DepositWriteMapper depositWriteMapper;
    
    @Autowired
    private BillPaymentReadMapper billPayReadMapper;
    
    @Autowired
    private WebBankQRTicketSerivce webBankQRTicketSerivce;
    
    @Autowired
    private WebBankTicketSerivce webBankTicketSerivce;
    
    @Autowired
    private WebBankAccessTokenSerivce webBankAccessTokenSerivce;
    
    @Autowired
    private WebankReconciliationReadMapper webankReconciliationReadMapper;
    
    @Autowired
    private BillReadMapper billReadMapper;
    
    @Autowired
    private WebankParamReadMapper webankParamReadMapper;
    
    @Autowired
    private BillPaymentReadMapper billPaymentReadMapper;
    
    @Autowired
    private FileConfiguration fileConfiguration;
    
    @Autowired
    private CustomerReadMapper customerReadMapper;
    
    @Autowired
    private BillIndependentService billIndependentService;
    
    @Autowired
    private AuthCodeService authCodeService;
    
    private static Logger logger = LoggerFactory.getLogger(WeBankServiceImpl.class);
    
    // 获取微信支付二维码
    @Override
    public WeBankPayRespDTO getWeBankPayQR(WeBankPayDTO payinfo)
        throws LandseaException, Exception
    {
        Assert.hasText(payinfo.getBusinessType(), "没有业务类型（账单或定金...）");
        Map<String, String> map = new HashMap<String, String>();
        map.put("orderId", payinfo.getOrderId());
        map.put("wbMerchantId", payinfo.getMerchantId());
        map.put("totalAmount", payinfo.getPrice());
        map.put("subject", payinfo.getMerchantName());
        map.put("desc", payinfo.getGoodsName());
        map.put("notifyUrl", QRinstance.getCallback_url());
        // map.put("attach", payinfo.getBusinessType());
        
        String ticket = webBankQRTicketSerivce.getTicket();
        String result = WeBankServiceUtil.getWeBankPayQR(map, ticket);
        WeBankPayRespDTO payresp = new WeBankPayRespDTO();
        payresp.setPayurl(result);
        return payresp;
    }
    
    // 收银台支付
    @Override
    public WeBankPayRespDTO getWeBankPay(WeBankPayDTO payinfo)
        throws LandseaException, Exception
    {
        Date nowTime = new Date(System.currentTimeMillis());
        
        SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyyMMddHHmmss");
        
        String reqTime = sdFormatter.format(nowTime);
        
        Calendar cal = Calendar.getInstance();
        cal.setTime(nowTime);
        cal.add(Calendar.MINUTE, 10);
        String payEndTime = sdFormatter.format(cal.getTime());
        
        Map<String, String> map = new HashMap<String, String>();
        map.put("webankAppId", instance.getApp_id()); // webank appid
        map.put("orderNo", payinfo.getOrderId()); // 订单编号
        map.put("amount", payinfo.getPrice()); // 交易金额
        map.put("reqTime", reqTime); // 请求时间
        map.put("merchantId", payinfo.getMerchantId()); // 商户编号
        map.put("merchantName", payinfo.getMerchantName()); // 商户名称
        if (payinfo.getBrefMerchantName() != null)
        {
            map.put("merchantAbbreviation", payinfo.getBrefMerchantName()); // 商户简称
        }
        map.put("userId", payinfo.getUserId().toString()); // 用户在合作方的userid
        map.put("redirectUrl", instance.getCallback_url()); // 支付成功后的跳转 URL
        map.put("goodsName", payinfo.getGoodsName()); // 商品名
        map.put("timeStart", reqTime);
        map.put("timeExpire", payEndTime);
        
        /// openId
        Customer customerDTO = customerReadMapper.selectByUserId(payinfo.getUserId());
        if (null == customerDTO)
        {
            LOG.error("getWeBankPay|微众收银台用户不存在,userId=" + payinfo.getUserId());
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_CUSTOMER_ISNULL);
        }
        
        map.put("subOpenid", customerDTO.getOpenId());
        map.put("subAppid", instance.getSubAppId());
        String ticket = webBankTicketSerivce.getTicket();
        
        // 每次支付都需要nonceTicket，有效期2分钟，获取时需要accessToken
        String accessToken = webBankAccessTokenSerivce.getAccessToken();
        String result = WeBankServiceUtil.syncPaymentInfo(map, ticket, accessToken);
        
        WeBankPayRespDTO payresp = new WeBankPayRespDTO();
        payresp.setPayurl(result);
        return payresp;
    }
    
    /**
     * 
     * [描述]：需要事务</br>
     *
     * @param callbackInfo
     * @return
     * @throws LandseaException
     * @throws Exception
     *
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    public String weBankCallback(WebankPayCallBackRequest callBackRequest)
        throws LandseaException, Exception
    {
        SimpleDateFormat sfd = new SimpleDateFormat("yyyyMMddHHmmss");
        
        // 微众收银台
        logger.info("weBankCallback|微众收银台业务处理！");
        
        if ("01".equals(callBackRequest.getTransStatus()))
        {
            // 表示回调成功
            logger.info("weBankCallback|回调结果-支付成功");
            String orderNo = callBackRequest.getOrderNo();
            String businessType = orderNo.substring(0, 2);
            String paytime = orderNo.substring(2, 16);
            Date time = sfd.parse(paytime);
            
            if ("E0".equals(businessType))
            {
                // 账单
                logger.info("微众收单成功，账单业务处理！");
                Integer billPaymentId = Integer.parseInt(orderNo.substring(16));
                BillPayment billPayment = new BillPayment();
                billPayment.setId(billPaymentId);
                billPayment.setStatus(SystemCodeEnum.PAY_TRUE.getCode());
                billPayment.setTransactionNo(orderNo);
                // 没有必要重新set支付类型
                //billPayment.setPayType(PayType.WEBANK_MOBILE);
                billPayment.setTime(time);
                billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                // 更新账单状态
                iBillPaymentService.updateBillpayment(billPayment);
                
                logger.info("更新账单状态成功！");
                BillPayment billPay = billPaymentReadMapper.selectByPrimaryKey(billPaymentId);
                String billType = billPay.getBillType();
                HashMap<String, Object> map = new HashMap<String, Object>();
                map.put("billId", billPay.getBillId());
                map.put("currentPayMoney", billPay.getMoney());
                map.put("payTime", paytime);
                String handlerName = "WebankCallBack" + billType;
                Object handerObject = appContext.getBean(handlerName);
                if (null == handerObject)
                {
                    LOG.error("WeBankServiceImpl|weBankCallback|Error|event is wrong,handlerName=" + handlerName);
                    throw LandseaException.createException(LandseaErrorMessageEnum.DDINGLOCK_CALLBACK_PARAM_ERROR);
                }
                
                IWebankCallbackHandler handler = (IWebankCallbackHandler)handerObject;
                // 开始处理
                handler.process(map);
                logger.info("判断合同是否生效");
            }
            else if ("E1".equals(businessType))
            {
                // 账单
                logger.info("微众收单成功，预定账单业务处理！");
                Integer billPaymentId = Integer.parseInt(orderNo.substring(16));
                BillPayment billPayment = new BillPayment();
                billPayment.setId(billPaymentId);
                billPayment.setStatus(SystemCodeEnum.PAY_TRUE.getCode());
                billPayment.setTransactionNo(orderNo);
                billPayment.setTime(time);
                billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                // 更新账单状态
                iBillPaymentService.updateBillpayment(billPayment);
                logger.info("更新账单状态成功！");                

                BillPayment billPay = billPaymentReadMapper.selectByPrimaryKey(billPaymentId);
                
                // 生成预定编号
                Integer depositId = billPay.getBillId();
                DepositDTO depositDTO = depositReadMapper.getDepositDetail(depositId);
                ProjectDetailDTO prj = projectService.getProjectDetail(depositDTO.getPrjId());
                String depositSn =
                    prj.getPrjCode() + new DecimalFormat("000000").format(depositReadMapper.getMaxContractCode());
                depositDTO.setDepositSn(depositSn);
                depositDTO.setId(depositId);
                // 没有必要重新set支付类型
                //depositDTO.setPayMethod(PayType.WEBANK_MOBILE);
                depositDTO.setStatus("_DS2");
                depositDTO.setPaySn(orderNo);
                depositDTO.setPayDate(time);
                depositDTO.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                depositWriteMapper.updateByPrimaryKeySelectiveDTO(depositDTO);
                
                //微众里面处理预定的往balancedSheet修改状态            
                billIndependentService.depUpdateBalanceSheet(depositId,depositSn, time);
                
                // 更新授权码为已使用状态
                authCodeService.updateCouponStatusAfterPay(QueryUesdCodeType.DEPOSIT, depositId);
                
                // 重新命名pdf文件名
                iDepositServiceImpl.renamePDF(DepositDTO.convertToDeposit(depositDTO));
            }
        }
        
        return "OK";
    }
    
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {BusinessException.class, Exception.class})
    public String weBankQRCallback(WebankQRPayCallBackRequestWapper webankQRPayCallBackRequestWapper)
        throws LandseaException, Exception
    {
        WebankQRPayCallBackRequest webankQRPayCallBackRequest = webankQRPayCallBackRequestWapper.getData();
        
        // 获取businessType
        String orderId = webankQRPayCallBackRequest.getOrderId();
        
        if (StringUtils.isEmpty(orderId))
        {
            logger.error("weBankQRCallback|orderId is empty.");
            throw LandseaException.createException(LandseaErrorMessageEnum.COMMON_REQUEST_PARAM_ERROR);
        }
//        // 如果存在isSubscribe，则是微信支付
//        String isSubscribe = webankQRPayCallBackRequest.getIsSubscribe();
//        // PATY2微信支付 PATY5支付宝支付
//        String payType = StringUtils.isNotEmpty(isSubscribe) ? "PATY2" : "PATY5";
        
        String businessType = orderId.substring(0, 2);
        String timeSring = orderId.substring(2, 16);
        Date time = DateUtil.getFormatDate(timeSring, "yyyyMMddHHmmss");
        
        if ("E0".equals(businessType))
        {
            // 账单
            logger.info("weBankQRCallback|微众收单成功，开始账单业务处理！");
            Integer paymentId = Integer.parseInt(orderId.substring(16));
            
            BillPayment billPayment = new BillPayment();
            try
            {
                billPayment.setId(paymentId);
                billPayment.setStatus(SystemCodeEnum.PAY_TRUE.getCode());
                billPayment.setTransactionNo(webankQRPayCallBackRequest.getChannelNo());
                billPayment.setTime(time);
                billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                // 更新账单状态
                iBillPaymentService.updateBillpayment(billPayment);
                
                BillPayment billPay = billPaymentReadMapper.selectByPrimaryKey(paymentId);
                String billType = billPay.getBillType();
                HashMap<String, Object> map = new HashMap<String, Object>();
                map.put("billId", billPay.getBillId());
                map.put("currentPayMoney", billPay.getMoney());
                map.put("payTime", time);
                String handlerName = "WebankCallBack" + billType;
                Object handerObject = appContext.getBean(handlerName);
                if (null == handerObject)
                {
                    LOG.error("weBankQRCallback|event is wrong|handlerName=" + handlerName);
                    throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_CALLBACK_BILLTYPE_ERROR);
                }
                
                IWebankCallbackHandler handler = (IWebankCallbackHandler)handerObject;
                // 开始处理
                handler.process(map);
                
                LOG.info("weBankQRCallback|handler is finished.");
            }
            catch (LandseaException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                logger.error("weBankQRCallback|账单回调处理失败.", e);
                throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_CALLBACK_BILL_ERROR, e);
            }
        }
        else if ("E1".equals(businessType))
        {
            try
            {
                // 预定
                logger.info("weBankQRCallback|微众收单成功，预定业务处理！");
                Integer billPaymentId = Integer.parseInt(orderId.substring(16));
                BillPayment billPayment = new BillPayment();
                billPayment.setId(billPaymentId);
                billPayment.setStatus(SystemCodeEnum.PAY_TRUE.getCode());
                billPayment.setTransactionNo(orderId);
                billPayment.setTime(time);
                billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                // 更新账单状态
                iBillPaymentService.updateBillpayment(billPayment);
                logger.info("更新账单状态成功！");                

                BillPayment billPay = billPaymentReadMapper.selectByPrimaryKey(billPaymentId);
                
                // 生成预定编号
                Integer depositId = billPay.getBillId();
                DepositDTO depositDTO = depositReadMapper.getDepositDetail(depositId);
                ProjectDetailDTO prj = projectService.getProjectDetail(depositDTO.getPrjId());
                String depositSn =
                    prj.getPrjCode() + new DecimalFormat("000000").format(depositReadMapper.getMaxContractCode());
                depositDTO.setDepositSn(depositSn);
                depositDTO.setId(depositId);
                depositDTO.setStatus("_DS2");
                depositDTO.setPaySn(orderId);
                depositDTO.setPayDate(time);
                depositDTO.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                depositWriteMapper.updateByPrimaryKeySelectiveDTO(depositDTO);
                
                //微众里面处理预定的往balancedSheet修改状态            
                billIndependentService.depUpdateBalanceSheet(depositId,depositSn, time);
                
                // 更新授权码为已使用状态
                authCodeService.updateCouponStatusAfterPay(QueryUesdCodeType.DEPOSIT, depositId);
                
                // 重新命名pdf文件名
                iDepositServiceImpl.renamePDF(DepositDTO.convertToDeposit(depositDTO));                
            }
            catch (Exception e)
            {
                logger.error("weBankQRCallback|预定业务处理失败.", e);
                throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_CALLBACK_BILL_ERROR, e);
            }
        }
        
        return "OK";
    }
    
    /**
     * 
     * [描述]：事务已添加</br>
     *
     * @param payinfo
     * @return
     * @throws LandseaException
     * @throws Exception
     *
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    @Override
    public WeBankPayCheckDTO checkPay(CheckPayDTO payinfo)
        throws LandseaException, Exception
    {
        String payType = "";
        String orderNo = "";
        String payStatus = "";
        String merchantId = "";
        WeBankPayCheckReqDTO paydto = new WeBankPayCheckReqDTO();
        BillPayment billPayment = new BillPayment();
        Deposit deposit = new Deposit();
        
        // ---------业务类型----------
        //
        // 根据不同业务类型，去数据库查询以下信息
        // payType获取支付类型
        // orderNo获取订单号
        // payStatus获取支付状态
        // merchantId获取商户号
        //
        // ------------------------
        if ("E0".equals(payinfo.getBusinessType()))
        {
            // ------账单------
            billPayment = billPayReadMapper.selectByPrimaryKey(payinfo.getBillPaymentId());
            if (billPayment == null)
            {
                throw new BusinessException("未查到账单信息");
            }
            payType = billPayment.getPayType();
            orderNo = billPayment.getOrderNo();
            payStatus = billPayment.getStatus();
            
            BillDTO billDto = billReadMapper.selectByPrimaryKey(billPayment.getBillId());
            Contract contract = contractReadMapper.selectByPrimaryKey(billDto.getContractId());
            WebankParam webankParam = webankParamReadMapper.selectByPrjId(contract.getProjectId());
            if (PayType.WEBANK_WECHAT.equals(payType))
            { // 微信
                merchantId = webankParam.getQrMerchantId();
            }
            else if (PayType.WEBANK_ALIPAY.equals(payType))
            { // 支付宝
                merchantId = webankParam.getQrAliMerchantId();
            }
            else if (PayType.WEBANK_MOBILE.equals(payType))
            { // 收银台
                merchantId = webankParam.getwMerchantId();
            }
            
        }
        else if ("E1".equals(payinfo.getBusinessType()))
        {
            // ------预定------
            deposit = depositReadMapper.selectByPrimaryKey(payinfo.getDepositId());
            if (deposit == null)
            {
                throw new BusinessException("未查到该预定信息");
            }
            payType = deposit.getPayMethod();
            orderNo = deposit.getOrderNo();
            if (deposit.getPayDate() == null)
            {
                payStatus = SystemCodeEnum.PAY_FALSE.getCode(); // 未支付
            }
            else
            {
                payStatus = SystemCodeEnum.PAY_TRUE.getCode(); // 已支付
            }
            
            WebankParam webankParam = webankParamReadMapper.selectByPrjId(deposit.getPrjId());
            if (PayType.WEBANK_WECHAT.equals(payType))
            { // 微信
                merchantId = webankParam.getQrMerchantId();
            }
            else if (PayType.WEBANK_ALIPAY.equals(payType))
            { // 支付宝
                merchantId = webankParam.getQrAliMerchantId();
            }
            else if (PayType.WEBANK_MOBILE.equals(payType))
            { // 收银台
                merchantId = webankParam.getwMerchantId();
            }
        }
        if (payType == null)
        {
            throw new BusinessException("尚未支付！");
        }
        
        // ---------支付方式-----------
        //
        // 根据不同支付方式（上步获取payType）调接口查询支付状态
        // 仅需订单号（orderNo），商户号（merchantId）两参数
        // 返回 WeBankPayCheckDTO 类型
        //
        // -------------------------
        WeBankPayCheckDTO result = new WeBankPayCheckDTO();
        if ("PATY2".equals(payType))
        { // 微信
            if (orderNo == null)
            {
                throw new BusinessException("没有订单号！");
            }
            // 收单
            if ("BPST1".equals(payStatus))
            {
                result.setTradeStatus("01");
            }
            else
            {
                paydto.setOrderId(orderNo);
                paydto.setWbMerchantId(merchantId);
                result = checkQRPayStatus(paydto);
                logger.info("收单微信查询结果：" + result);
            }
        }
        else if (PayType.WEBANK_ALIPAY.equals(payType))
        { // 支付宝
            if (orderNo == null)
            {
                throw new BusinessException("没有订单号！");
            }
            // 收单
            if ("BPST1".equals(payStatus))
            {
                result.setTradeStatus("01");
            }
            else
            {
                paydto.setOrderId(orderNo);
                paydto.setWbMerchantId(merchantId);
                result = checkQRPayStatus(paydto);
                logger.info("收单支付宝查询结果：" + result);
            }
        }
        else if (PayType.WEBANK_MOBILE.equals(payType))
        { // 收银台
            if (orderNo == null)
            {
                throw new BusinessException("没有订单号！");
            }
            if ("BPST1".equals(payStatus))
            {
                result.setTradeStatus("01");
            }
            else
            {
                paydto.setOrderId(orderNo);
                paydto.setWbMerchantId(merchantId);
                result = checkPayStatus(paydto);
                logger.info("收银台查询结果：" + result);
            }
        }
        else if (PayType.POS.equals(payType))
        { // POS
            if ("BPST1".equals(payStatus))
            {
                result.setTradeStatus("01");
            }
            else
            {
                result.setTradeStatus("02");
            }
        }
        
        // ---------更改记录状态,生成pdf------------
        //
        // ------- 支付成功后的处理（仅根据业务类型，与支付方式无关）
        //
        // ----------------------------------
        if ("01".equals(result.getTradeStatus()))
        { // 支付成功，生成pdf 【这里仅仅是收单支付成功】
            SimpleDateFormat sfd = new SimpleDateFormat("yyyyMMddHHmmss");
            String id = orderNo.substring(16);
            String time = orderNo.substring(2, 16);
            Date paytime = sfd.parse(time);
            if ("E0".equals(payinfo.getBusinessType()))
            { // ------账单------
                if ("BPST2".equals(billPayment.getStatus()))
                {
                    
                    Integer paymentId = Integer.parseInt(id);
                    // BillPayment billPayment = new BillPayment();
                    try
                    {
                        billPayment.setId(paymentId);
                        billPayment.setStatus("BPST1");
                        billPayment.setTransactionNo(result.getBizSeqNo());
                        billPayment.setTime(paytime);
                        billPayment.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                        // 更新账单状态
                        iBillPaymentService.updateBillpayment(billPayment);
                        logger.info("更新账单状态成功！");
                        BillPayment billPay = billPaymentReadMapper.selectByPrimaryKey(paymentId);
                        String billType = billPay.getBillType();
                        HashMap<String, Object> map = new HashMap<String, Object>();
                        map.put("billId", billPay.getBillId());
                        map.put("currentPayMoney", billPay.getMoney());
                        map.put("payTime", paytime);
                        String handlerName = "WebankCallBack" + billType;
                        Object handerObject = appContext.getBean(handlerName);
                        if (null == handerObject)
                        {
                            LOG.error("WeBankServiceImpl|weBankCallback|Error|event is wrong.");
                            throw LandseaException
                                .createException(LandseaErrorMessageEnum.DDINGLOCK_CALLBACK_PARAM_ERROR);
                        }
                        
                        IWebankCallbackHandler handler = (IWebankCallbackHandler)handerObject;
                        // 开始处理
                        handler.process(map);
                        logger.info("判断合同是否生效");
                    }
                    catch (Exception e)
                    {
                        logger.error("更新账单状态或更新合同状态失败", e);
                        throw new BusinessException("更新账单状态或更新合同状态失败");
                    }
                    
                }
                
            }
            else if ("E1".equals(payinfo.getBusinessType()))
            {// ------预定------
                Integer depositId = Integer.parseInt(id);
                DepositDTO depositDTO = depositReadMapper.getDepositDetail(depositId);
                ProjectDetailDTO prj = projectService.getProjectDetail(depositDTO.getPrjId());
                String depositSn =
                    prj.getPrjCode() + new DecimalFormat("000000").format(depositReadMapper.getMaxContractCode());
                depositDTO.setDepositSn(depositSn);
                depositDTO.setId(depositId);
                depositDTO.setStatus("_DS2");
                depositDTO.setPaySn(result.getBizSeqNo());
                depositDTO.setPayDate(paytime);
                depositDTO.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                depositWriteMapper.updateByPrimaryKeySelectiveDTO(depositDTO);
                // 重新命名pdf文件名
                iDepositServiceImpl.renamePDF(DepositDTO.convertToDeposit(depositDTO));
            }
        }
        return result;
    }
    
    // 微众收单支付状态查询
    public WeBankPayCheckDTO checkQRPayStatus(WeBankPayCheckReqDTO payinfo)
        throws LandseaException, Exception
    {
        JsonMapper jsonmapper = new JsonMapper();
        
        Map<String, String> map = new HashMap<String, String>();
        map.put("wbMerchantId", payinfo.getWbMerchantId());
        if (payinfo.getOrderId() != null)
            map.put("orderId", payinfo.getOrderId());
        if (payinfo.getChannelNo() != null)
            map.put("channelNo", payinfo.getChannelNo());
        // map.put("attach", payinfo.getBusinessType());
        
        String ticket = webBankQRTicketSerivce.getTicket();
        String result = WeBankServiceUtil.getWeBankQRPayCheck(map, ticket);
        return jsonmapper.fromJson(result, WeBankPayCheckDTO.class);
    }
    
    // 微众收银台支付状态查询
    public WeBankPayCheckDTO checkPayStatus(WeBankPayCheckReqDTO payinfo)
        throws LandseaException, Exception
    {
        SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyyMMddHHmmss");
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        
        Map<String, String> map = new HashMap<String, String>();
        map.put("webankAppId", instance.getApp_id());
        map.put("orderNo", payinfo.getOrderId());
        map.put("merchantId", payinfo.getWbMerchantId());
        
        String ticket = webBankTicketSerivce.getTicket();
        String result = WeBankServiceUtil.getWeBankPayCheck(map, ticket);
        String resultjson = transformJsonData(result);
        JSONObject json = JSONObject.fromObject(resultjson);
        JSONObject transResulti = json.getJSONArray("transResult").getJSONObject(0);
        WeBankPayCheckDTO dto = new WeBankPayCheckDTO();
        if ("11370000".equals(transResulti.getString("transStatus")))
        {// 支付成功
            String orderNo = transResulti.getString("orderNo");
            String time = orderNo.substring(2, 16);
            dto.setTradeStatus("01");
            dto.setBizSeqNo(orderNo);
            dto.setSuccess("true");
            dto.setCode("0");
            dto.setMsg("OK");
            dto.setTransactionTime(sf.format(sdFormatter.parse(time)));
        }
        /*
         * else if ("00".equals(transResulti.getString("transStatus"))) { // 支付中，生成二维码但没扫码支付 dto.setTradeStatus("00");
         * dto.setMsg("支付中（生成二维码但未扫码支付）"); }
         */
        else // if ("02".equals(transResulti.getString("transStatus")))
        { // 支付中，生成二维码但没扫码支付
            logger.error("checkPayStatus|收银台支付失败|" + result);
            dto.setTradeStatus("02");
            dto.setMsg("支付失败");
        }
        
        return dto;
    }
    
    private String transformJsonData(String sourceJson)
    {
        JSONObject jsonObject = null;
        try
        {
            jsonObject = JSONObject.fromObject(sourceJson);
        }
        catch (Exception e)
        {
            logger.error("解析报文出错：" + e.getMessage());
        }
        
        String type = jsonObject.getString("type");
        String data = "";
        try
        {
            data = jsonObject.getString("data");
        }
        catch (Exception e)
        {
            JSONObject jsonobjectData = jsonObject.getJSONObject("data");
            data = jsonobjectData.toString();
        }
        StringBuilder jsonBuild = new StringBuilder();
        jsonBuild.append("{")
            .append("\"type\":")
            .append("\"")
            .append(type)
            .append("\",")
            .append("\"data\":")
            .append(data)
            .append("}");
        logger.info("报文解析：" + jsonBuild.toString());
        return jsonBuild.toString();
    }
    
    /**
     * [描述]：接口weBankReconciliation</br>
     *
     * @param callbackEvent
     * @throws LandseaException
     * 
     */
    @Override
    public void weBankReconciliation(WebankQRPaymentNotify callbackEvent)
        throws LandseaException
    {
        LOG.info("weBankReconciliation|" + callbackEvent.toString());
        
        String type = callbackEvent.getType();
        if (!"FILE".equals(type))
        {
            throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_CALLBACK_RECONCILIATION_PARAM_ERROR);
        }
        
        WebankQRPaymentNotifyRequest paymentNotifyData = callbackEvent.getData();
        
        try
        {
            if (null != paymentNotifyData)
            {
                WebankReconciliation record = new WebankReconciliation();
                record.setWebankappid(paymentNotifyData.getWebankAppId());
                record.setFileId(paymentNotifyData.getFileId());
                record.setFileHash(paymentNotifyData.getFileHash());
                record.setToken(paymentNotifyData.getToken());
                record.setWorkDate(paymentNotifyData.getWorkDate());
                record.setCreatetime(new Date());
                webankReconciliationReadMapper.insert(record);
                
                // 下载文件
                downloadReconciliationFile(paymentNotifyData);
            }
        }
        catch (LandseaException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            LOG.error("weBankReconciliation|insert webankReconciliation failed.", e);
            throw LandseaException.createException(LandseaErrorMessageEnum.WEBANK_CALLBACK_RECONCILIATION_ERROR, e);
        }
    }
    
    /**
     * 
     * [简要描述]：下载对账文件</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-07-05)</br>
     *
     * @param paymentNotifyData
     * @throws LandseaException
     * 
     */
    public void downloadReconciliationFile(WebankQRPaymentNotifyRequest paymentNotifyData)
        throws LandseaException
    {
        try
        {
            String rootUrl = WeBankQRUtil.getInstance().getRoot_url();
            String appId = WeBankQRUtil.getInstance().getApp_id();
            String version = WeBankQRUtil.getInstance().getVersion();
            String downloadUrl = StringTools.splitJointPath(rootUrl, "api/base/file");
            StringBuilder sBurl = new StringBuilder();
            sBurl.append(downloadUrl);
            sBurl.append("?app_id=");
            sBurl.append(appId);
            sBurl.append("&token=");
            sBurl.append(paymentNotifyData.getToken());
            sBurl.append("&file_id=");
            sBurl.append(paymentNotifyData.getFileId());
            sBurl.append("&version=");
            sBurl.append(version);
            
            // 本地根目录
            String localRoot = fileConfiguration.getLocal();
            // 本地相对目录
            String localPath = fileConfiguration.getWebank_payfile_path();
            localPath = StringTools.splitJointPath(localRoot, localPath);
            
            // 文件名，当前时间秒级 例如：20170607152330.txt
            String fileName = DateUtil.getInstence().convertWeBankTime(new Date()) + ".wefile";
            
            LOG.info("downloadReconciliationFile|download url=" + sBurl.toString() + "|local path=" + localPath
                + ",fileName=" + fileName);
            
            // 判断本地保存路径是否存在
            FileTool.downLoadFromUrl(sBurl.toString(), fileName, localPath);
        }
        catch (Exception e)
        {
            LOG.error("downloadReconciliationFile|download failed.", e);
            //throw LandseaException.createException(LandseaErrorMessageEnum.COMMON_DOWNLOAD_ERROR, e);
        }
    }
}